"""
性能报告生成器

提供投资组合和策略的性能分析报告，包括收益率、风险指标、基准比较等。
"""

from typing import Dict, List, Optional, Any, Union
from datetime import datetime, timedelta
from dataclasses import dataclass, field
from decimal import Decimal
import math

from .report_generator import ReportGenerator, ReportConfig, ReportFormat, ReportType, ReportData


@dataclass
class PerformanceMetrics:
    """性能指标数据类"""
    # 收益指标
    total_return: Decimal = Decimal('0')  # 总收益率
    annualized_return: Decimal = Decimal('0')  # 年化收益率
    cumulative_return: Decimal = Decimal('0')  # 累计收益率
    
    # 风险指标
    volatility: Decimal = Decimal('0')  # 波动率
    annualized_volatility: Decimal = Decimal('0')  # 年化波动率
    max_drawdown: Decimal = Decimal('0')  # 最大回撤
    current_drawdown: Decimal = Decimal('0')  # 当前回撤
    
    # 风险调整收益指标
    sharpe_ratio: Decimal = Decimal('0')  # 夏普比率
    sortino_ratio: Decimal = Decimal('0')  # 索提诺比率
    calmar_ratio: Decimal = Decimal('0')  # 卡玛比率
    
    # 风险价值指标
    var_95: Decimal = Decimal('0')  # 95% VaR
    var_99: Decimal = Decimal('0')  # 99% VaR
    cvar_95: Decimal = Decimal('0')  # 95% CVaR
    cvar_99: Decimal = Decimal('0')  # 99% CVaR
    
    # 基准比较指标
    beta: Optional[Decimal] = None  # 贝塔系数
    alpha: Optional[Decimal] = None  # 阿尔法系数
    information_ratio: Optional[Decimal] = None  # 信息比率
    tracking_error: Optional[Decimal] = None  # 跟踪误差
    
    # 其他指标
    win_rate: Decimal = Decimal('0')  # 胜率
    profit_loss_ratio: Decimal = Decimal('0')  # 盈亏比
    recovery_factor: Decimal = Decimal('0')  # 恢复因子
    
    # 时间相关指标
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None
    trading_days: int = 0
    
    # 统计数据
    total_trades: int = 0
    winning_trades: int = 0
    losing_trades: int = 0
    avg_win: Decimal = Decimal('0')
    avg_loss: Decimal = Decimal('0')


@dataclass
class PerformanceData:
    """性能数据"""
    portfolio_id: str
    strategy_id: Optional[str] = None
    benchmark_id: Optional[str] = None
    
    # 时间序列数据
    dates: List[datetime] = field(default_factory=list)
    returns: List[Decimal] = field(default_factory=list)
    cumulative_returns: List[Decimal] = field(default_factory=list)
    portfolio_values: List[Decimal] = field(default_factory=list)
    benchmark_returns: List[Decimal] = field(default_factory=list)
    
    # 计算得出的指标
    metrics: PerformanceMetrics = field(default_factory=PerformanceMetrics)
    
    # 分解数据
    sector_performance: Dict[str, PerformanceMetrics] = field(default_factory=dict)
    asset_performance: Dict[str, PerformanceMetrics] = field(default_factory=dict)
    monthly_performance: Dict[str, Decimal] = field(default_factory=dict)
    yearly_performance: Dict[str, Decimal] = field(default_factory=dict)


class PerformanceReportGenerator(ReportGenerator):
    """性能报告生成器"""
    
    def __init__(self, config: Optional[ReportConfig] = None):
        """
        初始化性能报告生成器
        
        Args:
            config: 报告配置
        """
        super().__init__(config or ReportConfig(
            report_type=ReportType.PERFORMANCE,
            format=ReportFormat.JSON,
            title="性能分析报告"
        ))
        self.risk_free_rate = Decimal('0.03')  # 无风险利率，默认3%
    
    def collect_data(self, **kwargs) -> ReportData:
        """收集报告数据"""
        performance_data = kwargs.get('performance_data')
        if not performance_data:
            raise ValueError("需要提供performance_data参数")
        
        # 计算性能指标
        self._calculate_performance_metrics(performance_data)
        
        # 创建报告数据
        report_data = ReportData(
            title=self.config.title,
            subtitle=f"组合: {performance_data.portfolio_id}",
            summary=self._create_executive_summary(performance_data),
            metadata={
                "portfolio_id": performance_data.portfolio_id,
                "strategy_id": performance_data.strategy_id,
                "benchmark_id": performance_data.benchmark_id
            }
        )
        
        # 添加各个章节
        sections = [
            self.create_section("性能概览", self._create_performance_overview(performance_data)),
            self.create_section("风险分析", self._create_risk_analysis(performance_data)),
            self.create_section("基准比较", self._create_benchmark_comparison(performance_data)),
            self.create_section("行业分析", self._create_sector_analysis(performance_data)),
            self.create_section("资产分析", self._create_asset_analysis(performance_data)),
            self.create_section("时间序列分析", self._create_time_series_analysis(performance_data)),
            self.create_section("统计摘要", self._create_statistical_summary(performance_data))
        ]
        
        report_data.sections = sections
        return report_data
    
    def generate_content(self, data: ReportData) -> str:
        """生成报告内容"""
        return self.generate_to_json(data)
    
    def generate_performance_report(
        self,
        performance_data: PerformanceData,
        format_type: ReportFormat = ReportFormat.JSON,
        save_path: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        生成性能报告
        
        Args:
            performance_data: 性能数据
            format_type: 报告格式
            save_path: 保存路径
            
        Returns:
            报告数据
        """
        # 计算性能指标
        self._calculate_performance_metrics(performance_data)
        
        # 使用基类的generate_report方法
        self.config.format = format_type
        if save_path:
            self.config.output_path = save_path
        
        content = self.generate_report(performance_data=performance_data)
        
        # 返回原始数据用于进一步处理
        return {
            "report_content": content,
            "performance_data": performance_data,
            "metrics": performance_data.metrics
        }
    
    def _calculate_performance_metrics(self, data: PerformanceData) -> None:
        """计算性能指标"""
        if not data.returns or len(data.returns) == 0:
            return
        
        returns = [float(r) for r in data.returns]
        metrics = data.metrics
        
        # 基本统计
        metrics.trading_days = len(returns)
        metrics.start_date = data.dates[0] if data.dates else None
        metrics.end_date = data.dates[-1] if data.dates else None
        
        # 收益率计算
        metrics.total_return = Decimal(str(sum(returns)))
        metrics.cumulative_return = data.cumulative_returns[-1] if data.cumulative_returns else Decimal('0')
        
        # 年化收益率
        if metrics.trading_days > 0:
            trading_years = metrics.trading_days / 252  # 假设一年252个交易日
            if trading_years > 0:
                metrics.annualized_return = Decimal(str(
                    (float(metrics.cumulative_return + Decimal('1')) ** (1/trading_years) - 1)
                ))
        
        # 波动率计算
        if len(returns) > 1:
            mean_return = sum(returns) / len(returns)
            variance = sum((r - mean_return) ** 2 for r in returns) / (len(returns) - 1)
            metrics.volatility = Decimal(str(math.sqrt(variance)))
            metrics.annualized_volatility = metrics.volatility * Decimal(str(math.sqrt(252)))
        
        # 最大回撤计算
        self._calculate_drawdown(data)
        
        # 风险调整收益指标
        self._calculate_risk_adjusted_metrics(data)
        
        # VaR和CVaR计算
        self._calculate_var_cvar(data)
        
        # 基准比较指标
        if data.benchmark_returns:
            self._calculate_benchmark_metrics(data)
        
        # 交易统计
        self._calculate_trading_statistics(data)
    
    def _calculate_drawdown(self, data: PerformanceData) -> None:
        """计算回撤"""
        if not data.cumulative_returns:
            return
        
        cumulative = [float(r) for r in data.cumulative_returns]
        peak = cumulative[0]
        max_dd = 0
        current_dd = 0
        
        for value in cumulative:
            if value > peak:
                peak = value
                current_dd = 0
            else:
                current_dd = (peak - value) / peak
                max_dd = max(max_dd, current_dd)
        
        data.metrics.max_drawdown = Decimal(str(max_dd))
        data.metrics.current_drawdown = Decimal(str(current_dd))
    
    def _calculate_risk_adjusted_metrics(self, data: PerformanceData) -> None:
        """计算风险调整收益指标"""
        metrics = data.metrics
        
        # 夏普比率
        if metrics.annualized_volatility > 0:
            excess_return = metrics.annualized_return - self.risk_free_rate
            metrics.sharpe_ratio = excess_return / metrics.annualized_volatility
        
        # 索提诺比率（使用下行波动率）
        negative_returns = [float(r) for r in data.returns if r < 0]
        if negative_returns:
            downside_variance = sum(r ** 2 for r in negative_returns) / len(negative_returns)
            downside_volatility = Decimal(str(math.sqrt(downside_variance) * math.sqrt(252)))
            if downside_volatility > 0:
                excess_return = metrics.annualized_return - self.risk_free_rate
                metrics.sortino_ratio = excess_return / downside_volatility
        
        # 卡玛比率
        if metrics.max_drawdown > 0:
            metrics.calmar_ratio = metrics.annualized_return / metrics.max_drawdown
        
        # 恢复因子
        if metrics.max_drawdown > 0:
            metrics.recovery_factor = metrics.total_return / metrics.max_drawdown
    
    def _calculate_var_cvar(self, data: PerformanceData) -> None:
        """计算VaR和CVaR"""
        if not data.returns:
            return
        
        returns = sorted([float(r) for r in data.returns])
        n = len(returns)
        
        # 95% VaR
        var_95_index = int(n * 0.05)
        if var_95_index < n:
            data.metrics.var_95 = Decimal(str(abs(returns[var_95_index])))
            # 95% CVaR
            tail_returns = returns[:var_95_index+1]
            if tail_returns:
                data.metrics.cvar_95 = Decimal(str(abs(sum(tail_returns) / len(tail_returns))))
        
        # 99% VaR
        var_99_index = int(n * 0.01)
        if var_99_index < n:
            data.metrics.var_99 = Decimal(str(abs(returns[var_99_index])))
            # 99% CVaR
            tail_returns = returns[:var_99_index+1]
            if tail_returns:
                data.metrics.cvar_99 = Decimal(str(abs(sum(tail_returns) / len(tail_returns))))
    
    def _calculate_benchmark_metrics(self, data: PerformanceData) -> None:
        """计算基准比较指标"""
        if not data.benchmark_returns or len(data.benchmark_returns) != len(data.returns):
            return
        
        portfolio_returns = [float(r) for r in data.returns]
        benchmark_returns = [float(r) for r in data.benchmark_returns]
        
        # 计算贝塔系数
        if len(portfolio_returns) > 1:
            # 协方差和方差计算
            port_mean = sum(portfolio_returns) / len(portfolio_returns)
            bench_mean = sum(benchmark_returns) / len(benchmark_returns)
            
            covariance = sum((p - port_mean) * (b - bench_mean) 
                           for p, b in zip(portfolio_returns, benchmark_returns)) / (len(portfolio_returns) - 1)
            
            benchmark_variance = sum((b - bench_mean) ** 2 for b in benchmark_returns) / (len(benchmark_returns) - 1)
            
            if benchmark_variance > 0:
                data.metrics.beta = Decimal(str(covariance / benchmark_variance))
                
                # 阿尔法系数
                benchmark_return = Decimal(str(sum(benchmark_returns)))
                expected_return = self.risk_free_rate + data.metrics.beta * (benchmark_return - self.risk_free_rate)
                data.metrics.alpha = data.metrics.total_return - expected_return
        
        # 跟踪误差
        tracking_diffs = [p - b for p, b in zip(portfolio_returns, benchmark_returns)]
        if len(tracking_diffs) > 1:
            tracking_mean = sum(tracking_diffs) / len(tracking_diffs)
            tracking_variance = sum((d - tracking_mean) ** 2 for d in tracking_diffs) / (len(tracking_diffs) - 1)
            data.metrics.tracking_error = Decimal(str(math.sqrt(tracking_variance) * math.sqrt(252)))
            
            # 信息比率
            if data.metrics.tracking_error > 0:
                excess_return = data.metrics.total_return - Decimal(str(sum(benchmark_returns)))
                data.metrics.information_ratio = excess_return / data.metrics.tracking_error
    
    def _calculate_trading_statistics(self, data: PerformanceData) -> None:
        """计算交易统计"""
        if not data.returns:
            return
        
        positive_returns = [r for r in data.returns if r > 0]
        negative_returns = [r for r in data.returns if r < 0]
        
        data.metrics.total_trades = len(data.returns)
        data.metrics.winning_trades = len(positive_returns)
        data.metrics.losing_trades = len(negative_returns)
        
        # 胜率
        if data.metrics.total_trades > 0:
            data.metrics.win_rate = Decimal(str(data.metrics.winning_trades / data.metrics.total_trades))
        
        # 平均盈利和亏损
        if positive_returns:
            data.metrics.avg_win = Decimal(str(sum(positive_returns) / len(positive_returns)))
        if negative_returns:
            data.metrics.avg_loss = Decimal(str(sum(negative_returns) / len(negative_returns)))
        
        # 盈亏比
        if data.metrics.avg_loss != 0:
            data.metrics.profit_loss_ratio = abs(data.metrics.avg_win / data.metrics.avg_loss)
    
    def _create_executive_summary(self, data: PerformanceData) -> Dict[str, Any]:
        """创建执行摘要"""
        metrics = data.metrics
        
        return {
            "关键指标": {
                "总收益率": f"{float(metrics.total_return):.2%}",
                "年化收益率": f"{float(metrics.annualized_return):.2%}",
                "年化波动率": f"{float(metrics.annualized_volatility):.2%}",
                "最大回撤": f"{float(metrics.max_drawdown):.2%}",
                "夏普比率": f"{float(metrics.sharpe_ratio):.3f}",
                "卡玛比率": f"{float(metrics.calmar_ratio):.3f}"
            },
            "风险指标": {
                "95% VaR": f"{float(metrics.var_95):.2%}",
                "95% CVaR": f"{float(metrics.cvar_95):.2%}",
                "当前回撤": f"{float(metrics.current_drawdown):.2%}"
            },
            "交易统计": {
                "总交易次数": metrics.total_trades,
                "胜率": f"{float(metrics.win_rate):.2%}",
                "盈亏比": f"{float(metrics.profit_loss_ratio):.2f}"
            }
        }
    
    def _create_performance_overview(self, data: PerformanceData) -> Dict[str, Any]:
        """创建性能概览"""
        metrics = data.metrics
        
        return {
            "收益指标": {
                "总收益率": float(metrics.total_return),
                "累计收益率": float(metrics.cumulative_return),
                "年化收益率": float(metrics.annualized_return),
                "平均日收益率": float(metrics.total_return / metrics.trading_days) if metrics.trading_days > 0 else 0
            },
            "时间统计": {
                "开始日期": self.format_datetime(metrics.start_date, 'date') if metrics.start_date else None,
                "结束日期": self.format_datetime(metrics.end_date, 'date') if metrics.end_date else None,
                "交易天数": metrics.trading_days,
                "交易年数": round(metrics.trading_days / 252, 2) if metrics.trading_days > 0 else 0
            }
        }
    
    def _create_risk_analysis(self, data: PerformanceData) -> Dict[str, Any]:
        """创建风险分析"""
        metrics = data.metrics
        
        return {
            "波动率指标": {
                "日波动率": float(metrics.volatility),
                "年化波动率": float(metrics.annualized_volatility),
                "下行波动率": "需要计算"  # 可以添加具体计算
            },
            "回撤分析": {
                "最大回撤": float(metrics.max_drawdown),
                "当前回撤": float(metrics.current_drawdown),
                "恢复因子": float(metrics.recovery_factor)
            },
            "风险价值": {
                "95% VaR": float(metrics.var_95),
                "99% VaR": float(metrics.var_99),
                "95% CVaR": float(metrics.cvar_95),
                "99% CVaR": float(metrics.cvar_99)
            },
            "风险调整收益": {
                "夏普比率": float(metrics.sharpe_ratio),
                "索提诺比率": float(metrics.sortino_ratio),
                "卡玛比率": float(metrics.calmar_ratio)
            }
        }
    
    def _create_benchmark_comparison(self, data: PerformanceData) -> Dict[str, Any]:
        """创建基准比较"""
        metrics = data.metrics
        
        if not data.benchmark_returns:
            return {"说明": "无基准数据"}
        
        return {
            "相对表现": {
                "贝塔系数": float(metrics.beta) if metrics.beta else None,
                "阿尔法系数": float(metrics.alpha) if metrics.alpha else None,
                "信息比率": float(metrics.information_ratio) if metrics.information_ratio else None,
                "跟踪误差": float(metrics.tracking_error) if metrics.tracking_error else None
            },
            "基准对比": {
                "组合收益率": float(metrics.total_return),
                "基准收益率": float(sum(data.benchmark_returns)) if data.benchmark_returns else 0,
                "超额收益": float(metrics.total_return - sum(data.benchmark_returns)) if data.benchmark_returns else 0
            }
        }
    
    def _create_sector_analysis(self, data: PerformanceData) -> Dict[str, Any]:
        """创建行业分析"""
        if not data.sector_performance:
            return {"说明": "无行业分解数据"}
        
        sector_data = {}
        for sector, metrics in data.sector_performance.items():
            sector_data[sector] = {
                "收益率": float(metrics.total_return),
                "波动率": float(metrics.volatility),
                "夏普比率": float(metrics.sharpe_ratio),
                "最大回撤": float(metrics.max_drawdown)
            }
        
        return {"行业表现": sector_data}
    
    def _create_asset_analysis(self, data: PerformanceData) -> Dict[str, Any]:
        """创建资产分析"""
        if not data.asset_performance:
            return {"说明": "无资产分解数据"}
        
        asset_data = {}
        for asset, metrics in data.asset_performance.items():
            asset_data[asset] = {
                "收益率": float(metrics.total_return),
                "波动率": float(metrics.volatility),
                "夏普比率": float(metrics.sharpe_ratio),
                "最大回撤": float(metrics.max_drawdown)
            }
        
        return {"资产表现": asset_data}
    
    def _create_time_series_analysis(self, data: PerformanceData) -> Dict[str, Any]:
        """创建时间序列分析"""
        return {
            "月度表现": {k: float(v) for k, v in data.monthly_performance.items()},
            "年度表现": {k: float(v) for k, v in data.yearly_performance.items()},
            "时间序列数据": {
                "日期": [self.format_datetime(d, 'date') for d in data.dates],
                "收益率": [float(r) for r in data.returns],
                "累计收益率": [float(r) for r in data.cumulative_returns],
                "组合价值": [float(v) for v in data.portfolio_values]
            }
        }
    
    def _create_statistical_summary(self, data: PerformanceData) -> Dict[str, Any]:
        """创建统计摘要"""
        if not data.returns:
            return {"说明": "无收益率数据"}
        
        returns = [float(r) for r in data.returns]
        
        # 基本统计
        mean_return = sum(returns) / len(returns) if returns else 0
        sorted_returns = sorted(returns)
        n = len(sorted_returns)
        
        return {
            "描述性统计": {
                "样本数量": n,
                "均值": mean_return,
                "中位数": sorted_returns[n//2] if n > 0 else 0,
                "标准差": float(data.metrics.volatility),
                "最小值": min(returns) if returns else 0,
                "最大值": max(returns) if returns else 0,
                "偏度": "需要计算",  # 可以添加偏度计算
                "峰度": "需要计算"   # 可以添加峰度计算
            },
            "分位数": {
                "5%": sorted_returns[int(n*0.05)] if n > 0 else 0,
                "25%": sorted_returns[int(n*0.25)] if n > 0 else 0,
                "75%": sorted_returns[int(n*0.75)] if n > 0 else 0,
                "95%": sorted_returns[int(n*0.95)] if n > 0 else 0
            }
        }